import serial
import sys
import os
import time
import re
import serial.tools.list_ports
import binascii

class Battery:

    def __init__(self, voltage=0, capacity=0, serialName='/dev/ttyS0'):
        self.MAX_LOOP_NUM = 3
        self.serialName = serialName
        self.capacity = capacity
        self.voltage = voltage
        self.HexLine = 0
        self.ser = None
     #   Battery.SetUartCom(self)
        Battery.AutoGetUartCom(self)
        """
        self.ser = serial.Serial(self.serialName, 9600, timeout=1)  # timeout=30 30s
        print("可用端口名>>>", self.ser.name)
        #self.ser.open()
        #print("open success")
        if(self.ser.is_open):
            print("open success")
        else:
            print("open failed")
        """
    def SetUartCom(self):
        self.ser = serial.Serial(self.serialName, 9600, timeout=1)  # timeout=30 30s
        print("可用端口名>>>", self.ser.name)
        #self.ser.open()
        if (self.ser.is_open):
            print("open success")
        else:
            print("open failed")


    def AutoGetUartCom(self):
        plist = list(serial.tools.list_ports.comports())

        if len(plist) <= 0:
            print("没有发现端口!")
        else:
            plist_0 = list(plist[0])
            self.serialName = plist_0[0]  # 先自动检测串口， 检测到可用串口，取出串口名
        # ser = serial.Serial("COM6", 115200, timeout=30)
        try:
            self.ser = serial.Serial(self.serialName, 9600, timeout=1)  # timeout=30 30s
            print("可用端口名>>>", self.ser.name)

        except BaseException as e:
            print(e)
            exit(0)


    def CloseUartCom(self):
        self.ser.close()
        if (self.ser.is_open):
            print("Close Failed")
        else:
            print("Close Success")

    def waitForCmdOKRsp(self):
        maxloopNum = 0
        while True:
            self.line = self.ser.readline()  # 读取一行数据

            maxloopNum = maxloopNum + 1  # 计算读取长度
            try:
                print("Rsponse : %s" % self.line.decode('utf-8'))  # 串口接收到数据，然后显示
            except:
                pass
            if (re.search(b'~', self.line)):
                return 1

            #elif (maxloopNum > self.MAX_LOOP_NUM):
            #elif (maxloopNum > self.MAX_LOOP_NUM):
            else:
                return 0
            #   sys.exit(0)


    def sendAT_Cmd(self,serInstance,atCmdStr, waitforOk=1) :
        # print("Command: %s" % atCmdStr)
        serInstance.write(atCmdStr.encode('utf-8'))
        #self.ser.write(0x00)
        # or define b'string',bytes should be used not str
        if (waitforOk == 1):
            loop_Num=self.MAX_LOOP_NUM
            while loop_Num>0:
                if(Battery.waitForCmdOKRsp(self)):
                    break
                else:
                    print("Command: %s" % atCmdStr)
                    serInstance.write(atCmdStr.encode('utf-8'))
                loop_Num=loop_Num-1
        else:
           Battery.waitForCmdRsp(self)

    def AnalysisData(self):
        # hlen=len(self.line)-1
        # print(len(self.line))
        if(len(self.line)!=0):   
            if( (self.line[0] == 0x3A) and (self.line[-1] == 0x7e)):
                if((self.line[3] == 0x38) and (self.line[4] == 0x32) ):
                    vol = self.line[25:29]
                    print('volatage is : 0x' + vol.decode())
                    volf = int(vol, 16) / 1000.0 * 2.0
                    print('voltage is: %.3fV' % volf)
                    print("电压: %d" % self.voltage, "mv")
                    return self.voltage
                elif ((self.line[3] == 0x39) and (self.line[4] == 0x33)):
                    vol = self.line[11:13]
                    print('volatage is : 0x' + vol.decode())
                    self.capacity = int(vol, 16)
                    print("百分比: %d" % self.capacity, "%")
                    # self.capacity=((self.line[11]-0x30)*10+(self.line[12]-0x30))
                    # print("百分比: %d" % self.capacity, "%")
                    return self.capacity
                else :
                    print("其他命令")
                    return 0
            else:
                print("解析错误" )
            #    print("146h,少读内容：", left, "共", left.__len__(), "个字节")
                return 0
        else :
            print("no ack" )
            return 0

    def GetRealInformation(self):
        Battery.sendAT_Cmd(self,self.ser,':000200000ee8~',1)  # 请求实时信息

    def GetElectricQuantity(self):
        Battery.sendAT_Cmd(self,self.ser, ':000200000ee8~', 1)  # 请求实时信息
        return Battery.AnalysisData(self)

    def GetCapacityPercent(self):
        Battery.sendAT_Cmd(self,self.ser, ':001300000ee6~', 1)  # 读取容量百分比
        return Battery.AnalysisData(self)

    def GetVersion(self):
        Battery.sendAT_Cmd(self,self.ser, ':000900000ee1~', 1)  # 获取版本信息
        return Battery.AnalysisData(self)

class BatteryMonitor:
    def __init__(self):
        self.bat = YunFanBattery()
        self.quantity = 0

    def run(self):
        while True:
            try:
                ret = bat.GetElectricQuantity()
                if ret!=0:
                    self.quantity = ret
                    print("Battery: %d%%"%(self.quantity))
            except BaseException as e:
                print(e)
                break
            time.sleep(1)


if __name__ == "__main__":
    YunFanBattery = Battery()
    YunFanBattery.GetElectricQuantity()
    YunFanBattery.GetCapacityPercent()
    YunFanBattery.GetVersion()
    YunFanBattery.CloseUartCom()
    sys.exit(0)

